package com.jl.utils;

import com.jl.annatation.Transfer;
import com.jl.model.ParamModel;
import com.jl.model.ParamVo;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class CommonUtils {

    public static <T> T packParam(Class<T> tClass,Class<? extends  Enum>... enums) throws Exception {
        T t = tClass.newInstance();
        for (Class<? extends Enum> anEnum : enums) {
            Field[] declaredFields = t.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                if (toLowerCaseFirstOne(anEnum.getSimpleName()).equals(declaredField.getName())){
                    List<ParamModel> list = new ArrayList<>();
                    Enum[] enumConstants = anEnum.getEnumConstants();
                    Method getId = anEnum.getMethod("getId");
                    Method getDesc = anEnum.getMethod("getDesc");
                    for (Enum enumConstant : enumConstants) {
                        ParamModel paramModel = new ParamModel();
                        paramModel.setId(getId.invoke(enumConstant).toString());
                        paramModel.setName(getDesc.invoke(enumConstant).toString());
                        list.add(paramModel);
                    }
                    PropertyUtils.setProperty(t,declaredField.getName(),list);
                }
            }
        }
        return t;
    }

    public static String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }


    public static void transfer(Object object) throws Exception {
        if (object!=null){
            Field[] declaredFields = object.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                Transfer annotation = declaredField.getAnnotation(Transfer.class);
                if (annotation!=null){
                    Class<? extends Enum> target = annotation.target();
                    Enum[] enumConstants = target.getEnumConstants();
                    declaredField.setAccessible(true);
                    Object o = declaredField.get(object);
                    if (o!=null){
                        String str = o.toString();
                        Method getId = target.getMethod("getId");
                        Method getDesc = target.getMethod("getDesc");
                        StringBuilder stringBuilder = new StringBuilder();
                        for (Enum enumConstant : enumConstants) {
                            if (!str.contains(",")){ //单选
                                if (str.equals(getId.invoke(enumConstant).toString())){
                                    PropertyUtils.setProperty(object,declaredField.getName(),getDesc.invoke(enumConstant).toString());
                                    break;
                                }
                            }else {  //多选则拼接 用逗号隔开
                                String[] split = str.split(",");
                                for (String s : split) {
                                    if (s.equals(getId.invoke(enumConstant).toString())){
                                        stringBuilder.append(getDesc.invoke(enumConstant).toString()).append(",");
                                        break;
                                    }
                                }
                            }
                        }
                        if (stringBuilder.length()>0){
                            PropertyUtils.setProperty(object,declaredField.getName(),stringBuilder.substring(0,stringBuilder.length()-1));
                        }
                    }

                }
            }
        }
    }

    public static void setParam(Object source,Object target) throws Exception {
        Field[] sourceField = source.getClass().getDeclaredFields();
        Field[] targetField = target.getClass().getDeclaredFields();
        for (Field t : targetField) {
            Transfer annotation = t.getAnnotation(Transfer.class);
            t.setAccessible(true);
            for (Field s : sourceField) {
                if (t.getName().equals(s.getName())){
                    s.setAccessible(true);
                    if (annotation!=null){
                        Object o = s.get(source);
                        if (o!=null){
                            String targetValue = o.toString();
                            if (targetValue.contains(",")){ //多选
                                String[] split = targetValue.split(",");
                                List<ParamVo> list = new ArrayList<>();
                                for (String s1 : split) {
                                    ParamVo paramVo = new ParamVo();
                                    paramVo.setId(s1);
                                    paramVo.setName(getEnumDescById(annotation.target(), s1,"getDesc"));
                                    list.add(paramVo);
                                }
                                PropertyUtils.setProperty(target,t.getName(),list);
                            }else {
                                ParamVo paramVo = new ParamVo();
                                paramVo.setId(targetValue);
                                paramVo.setName(getEnumDescById(annotation.target(),targetValue,"getDesc"));
                                PropertyUtils.setProperty(target,t.getName(),paramVo);
                            }
                        }
                    }else {
                        Object o = s.get(source);
                        if (o!=null){
                            PropertyUtils.setProperty(target,t.getName(),convert(t.getType(),o.toString()));
                        }
                    }
                    break;
                }
            }
        }
    }

    public static String getEnumDescById(Class<? extends Enum> clazz,String id,String method) {
        Enum[] enumConstants = clazz.getEnumConstants();
        Method getId =null ;
        Method getDesc = null;
        try {
            getId = clazz.getMethod("getId");
            getDesc = clazz.getMethod(method);
            for (Enum enumConstant : enumConstants) {
                if ((!StringUtils.isEmpty(id))&&id.equals(getId.invoke(enumConstant).toString())){
                    return getDesc.invoke(enumConstant).toString();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Object convert(Class<?> source,Object target){
        if (!source.isInstance(target.getClass())){
            if (source.getName().contains("Integer")){
                return Integer.valueOf(target.toString());
            }else if(source.getName().contains("BigDecimal")){
                return new BigDecimal(target.toString());
            }else if(source.getName().contains("String")){
                return String.valueOf(target);
            }
        }else {
            return target;
        }
        return null;
    }


}
